package cn.ligoo.part.web.filter;

import java.io.IOException;
import java.util.List;

import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils;

import cn.ligoo.part.domain.SysModAction;
import cn.ligoo.part.domain.SysModule;
import cn.ligoo.part.domain.UserInfo;
import cn.ligoo.part.service.Facade;
import cn.ligoo.part.web.Constants;
import cn.ligoo.part.web.ControllerUtils;

/**
 * @author Jin,QingHua
 */
public class PermissionFilter extends OncePerRequestFilter {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws ServletException, IOException {

		// logger.debug("getContextPath:={}", request.getContextPath());
		logger.debug("------------>getRequestURI:={}", request.getRequestURI());
		// logger.debug("getRequestURL:={}", request.getRequestURL());

		String requestURI = request.getRequestURI();
		String mod_url = StringUtils.substringBetween(requestURI, "/platform/", "/");

		// 链接不在权限控制的范围内的，放行
		if (null == mod_url || mod_url.length() == 0) {
			logger.debug("OOOOOOOOOO-->mod_url:={}", mod_url);
			chain.doFilter(request, response);
			return;
		} else {
			logger.debug("============>mod_url:={}", mod_url);
		}

		// 超级用户无视链接url权限filter，放行
		UserInfo userInfo = (UserInfo) WebUtils.getSessionAttribute(request, Constants.SESSION_USER_INFO);
		if (null != userInfo && null != userInfo.getIs_admin() && userInfo.getIs_admin() == 1) {
			logger.debug("OOOOOOOOOO-->is_admin:={}", userInfo.getIs_admin());
			chain.doFilter(request, response);
			return;
		}

		String action = StringUtils.substringAfter(requestURI, "/platform/" + mod_url + "/");
		action = StringUtils.split(action, "/")[0];
		logger.debug("action:={}", action);
		// 给json开绿色通道，基本上只是取数据，放行
		if (action.startsWith("json") || action.startsWith("format")) {
			logger.debug("OOOOOOOOOO-->action.startsWith('json'):={}", action.startsWith("json"));
			chain.doFilter(request, response);
			return;
		}

		ServletContext servletContext = super.getFilterConfig().getServletContext();
		WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
		Facade facade = (Facade) wac.getBean("facade");

		// 此处应该保证获取到唯一的SysModule。有时mod_url相同时，要带要mod_code
		SysModule t = new SysModule();
		t.setMod_url(mod_url);
		SysModule sysModule = facade.getSysModuleService().getSysModule(t);

		// 链接都末有的, 找不到对应的Controller, SpringMVC会报错，这儿直接返回个404吧。
		if (null == sysModule) {
			logger.warn("WWWWWWWWWW-->null == sysModule:={}", null == sysModule);
			response.sendError(HttpServletResponse.SC_NOT_FOUND);
			return;
		}

		logger.debug("mod_name:={}", sysModule.getMod_name());
		// 公共的（is_public:=1），放行
		if (null != sysModule.getIs_public() && sysModule.getIs_public() == 1) {
			logger.debug("OOOOOOOOOO-->is_public:={}", sysModule.getIs_public());
			chain.doFilter(request, response);
			return;
		}

		// 授权表中取授权
		List<SysModAction> sysModActionList = ControllerUtils.getSysModActionList(facade, userInfo);
		// 末有的，forbidden
		if (null == sysModActionList) {
			logger.warn("WWWWWWWWWW-->null == sysModActionList:={}", null == sysModActionList);
			chain.doFilter(request, response);
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		boolean hasPermissions = false;
		String action_code = null;
		for (SysModAction sma : sysModActionList) {
			if (sysModule.getMod_code() == sma.getMod_code()) {
				action_code = sma.getAction_code();
				logger.debug("action_code:={};mod_name:{}", sma.getAction_code(), sysModule.getMod_name());
				if (action.startsWith("execute") && "X".equalsIgnoreCase(action_code)) {
					hasPermissions = true;
					logger.debug("OOOOOOOOOO-->list permission=true");
					break;
				}
				if (action.startsWith("search") && "S".equalsIgnoreCase(action_code)) {
					hasPermissions = true;
					logger.debug("OOOOOOOOOO-->list permission=true");
					break;
				}
				if (action.startsWith("edit") && "U".equalsIgnoreCase(action_code)) {
					hasPermissions = true;
					logger.debug("OOOOOOOOOO-->edit permission=true");
					break;
				}
				if (action.startsWith("add") && "C".equalsIgnoreCase(action_code)) {
					hasPermissions = true;
					logger.debug("OOOOOOOOOO-->add permission=true");
					break;
				}
				if (action.startsWith("view") && "R".equalsIgnoreCase(action_code)) {
					hasPermissions = true;
					logger.debug("OOOOOOOOOO-->view permission=true");
					break;
				}
				if (action.startsWith("save")
						&& ("U".equalsIgnoreCase(action_code) || "C".equalsIgnoreCase(action_code))) {
					hasPermissions = true;
					logger.debug("OOOOOOOOOO-->save permission=true");
					break;
				}
				if (action.startsWith("delete") && "D".equalsIgnoreCase(action_code)) {
					hasPermissions = true;
					logger.debug("OOOOOOOOOO-->delete permission=true");
					break;
				}
				if (action.startsWith("export") && "E".equalsIgnoreCase(action_code)) {
					hasPermissions = true;
					logger.debug("OOOOOOOOOO-->delete permission=true");
					break;
				}
				if (action.startsWith("export") && "I".equalsIgnoreCase(action_code)) {
					hasPermissions = true;
					logger.debug("OOOOOOOOOO-->delete permission=true");
					break;
				}
			}
		}

		if (!hasPermissions) {
			logger.warn("WWWWWWWWWW-->hasPermissions:={}", hasPermissions);
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}
		logger.debug("OOOOOOOOOO-->hasPermissions:={}", hasPermissions);

		chain.doFilter(request, response);
	}
}
